/*******************************************************************************
 * @file fdt_vector.h
 * @brief  inter process Fast Data Transfer
 *
 *
 * Author: Chrisx
 *
 * Copyright (c) 2016 Chrisx. All Rights Reserved.
 *
 * CONFIDENTIALITY AND LIMITED USE
 *
 * This software, including any software of third parties embodied herein,
 * contains information and concepts which are confidential to Chrisx
 * and such third parties. This software is licensed for use
 * solely in accordance with the terms and conditions of the applicable
 * license agreement with Kevinx or its authorized distributor.
 ************************************************************************************/
#ifndef __FDT_VECTOR_H__
#define __FDT_VECTOR_H__
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#ifndef __USE_GNU
#define __USE_GNU
#endif
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

struct fdt_vector {
    int fd;
    void* base_addr;

    char name[32];
    unsigned int obj_size;
    unsigned int size;    

    void (*constructor)(struct fdt_vector* vec);
    void (*destructor)(struct fdt_vector* vec);
};

int fdt_vector_create(struct fdt_vector* vec);
int fdt_vector_destory(struct fdt_vector* vec);

/**
 * @brief Enlarge or shrink vector size
 *
 * Enlarge or shrink vector size
 *
 * @param vec Pinter to FDT vector object
 * @param new_size New size of vector
 * @param maymove  If maymove = 1, the base_addr of vector may be relocated, then
 *             absolute  pointers  into  the  old  location  become  invalid (offsets relative to the starting address should be
 *             employed).
 *
 * @return -1 - on failure, 0 - on sucess
 *
 */
int fdt_vector_resize(struct fdt_vector* vec, unsigned int new_size, int maymove);

void* fdt_get_elem_pointer(struct fdt_vector* vec,
                           int i,
                           int (*lock)(int, unsigned int, unsigned int));

void fdt_put_elem_pointer(struct fdt_vector* vec,
                          int i,
                          int (*unlock)(int, unsigned int, unsigned int));


int fdt_unlock(int fd, unsigned int start, unsigned int off);

int fdt_wr_lock(int fd,  unsigned int start, unsigned int off);
int fdt_wr_trylock(int fd,  unsigned int start, unsigned int off);

int fdt_rd_lock(int fd,  unsigned int start, unsigned int off);
int fdt_rd_trylock(int fd,  unsigned int start, unsigned int off);

#define FDT_SIZEOF(vec) ((vec)->size * (vec)->obj_size)

#define fdt_get_ptr(vec, pos, i) ( {       \
        pos = (typeof(pos))fdt_get_elem_pointer(vec, i, fdt_wr_lock); \
        pos; \
})

#define fdt_try_get_ptr(vec, pos, i) ( {       \
        pos = (typeof(pos))fdt_get_elem_pointer(vec, i, fdt_wr_trylock); \
        pos; \
})

#define fdt_get_rdptr(vec, pos, i) ( {       \
        pos = (typeof(pos))fdt_get_elem_pointer(vec, i, fdt_rd_lock); \
        pos; \
})

#define fdt_try_get_rdptr(vec, pos, i) ( {       \
        pos = (typeof(pos))fdt_get_elem_pointer(vec, i, fdt_rd_trylock); \
        pos; \
})

#define fdt_put_ptr(vec, i) ( {\
        fdt_put_elem_pointer(vec, i, fdt_unlock); \
})
        
#endif /* __FDT_VECTOR_H__ */
